package com.zhouchj.elasticsearch.update;

import cn.hutool.core.collection.CollUtil;
import com.zhouchj.elasticsearch.basic.EsQueryBuilderUtil;
import com.zhouchj.elasticsearch.basic.SFunction;
import com.zhouchj.elasticsearch.query.EsBasicQuery;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;

import java.util.*;

/**
 * Lambda更新
 *
 * @author zhouchj
 * @date 2023/8/24
 */
public class EsUpdate<T, Column extends SFunction<T, ?>, Children extends EsBasicQuery<T, Column, Children>>
        extends EsBasicQuery<T, Column, Children> {

    /**
     * 更新字段和值
     * key->字段名称 value->字段值
     */
    protected final Map<String, Object> param = new HashMap<>();

    /**
     * 需要更新的字段编号
     */
    protected List<Long> ids = new ArrayList<>();

    protected EsUpdate(Class<T> clazz,
                       IndexCoordinates index,
                       ElasticsearchRestTemplate elasticsearchRestTemplate) {
        super(clazz, index, elasticsearchRestTemplate);
    }

    /**
     * 设置id
     * 如果传入的id为null则不进行任何操作
     * 如果设置了id优先使用id 而非查询条件
     *
     * @param id id
     * @return this
     */
    public Children id(Long id) {
        if (Objects.nonNull(id)) {
            this.ids.add(id);
        }
        return typedThis;
    }

    /**
     * 设置id
     * 如果传入的集合为空则不进行任何操作
     * 会过滤集合中的null值
     * 如果设置了id优先使用id 而非查询条件
     *
     * @param ids id集合
     * @return this
     */
    public Children id(List<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return typedThis;
        }
        ids.stream()
                .filter(Objects::nonNull)
                .forEach(ids::add);
        return typedThis;
    }


    /**
     * 设置值
     *
     * @param column 字段
     * @param value  需要设置的值
     * @return this
     */
    public Children set(Column column, Object value) {
        return set(true, column, value);
    }

    /**
     * 设置值
     *
     * @param condition 是否进行设置
     * @param column    字段
     * @param value     需要设置的值
     * @return this
     */
    public Children set(boolean condition, Column column, Object value) {
        if (!condition || Objects.isNull(value)) {
            return typedThis;
        }

        boolean nestField = this.isNestField(column);
        // 嵌套字段转成Map
        if (nestField) {
            if (value instanceof Iterable) {
                value = EsQueryBuilderUtil.convertEntityToListMap(value);
            } else {
                value = EsQueryBuilderUtil.convertEntityToMap(value);
            }
        }

        String fieldName = this.convertToEsFieldName(clazz, column);
        param.put(fieldName, value);
        return typedThis;
    }

}
